#include "SocketProtocoloPlano.h"
#include "../utils/UtilString.h"

SocketProtocoloPlano::SocketProtocoloPlano() {

}
SocketProtocoloPlano::SocketProtocoloPlano(int fd):Socket(fd){

}

int SocketProtocoloPlano::send(const Mensaje& mensaje){

	std::string stream = pp.serializar(mensaje);
	std::string toWrite = UtilString::TOlenghtStringStringValue(stream);

	std::string longMensaje = UtilString::intToString(stream.size());
	std::string tamanioString =UtilString::fixedSize(longMensaje,PLANO_HEADER_MAX_LONG);

	//Agrego la cabecera de dimension del mensaje
	toWrite = tamanioString + toWrite;

	int error = this->send(toWrite.c_str(),toWrite.size());

	return error;
}


int SocketProtocoloPlano::send(const char* stream, int size){
	int bytesMandados =  0, bytesTotales = 0;

	while (bytesTotales < size){
		bytesMandados = ::send(this->fd, stream + bytesTotales, size - bytesTotales, 0);

		if (bytesMandados == SOCKET_ERROR)
		{
			return SOCKET_ERROR;
		}

		bytesTotales += bytesMandados;
	}

	return SOCKET_EXITO;
}


int SocketProtocoloPlano::receive(char* stream, int size){
	int bytesRecibidos = 0, bytesTotales = 0;

	while (bytesTotales < size){
		bytesRecibidos = ::recv(this->fd, stream + bytesTotales, size - bytesTotales, 0);

		if (bytesRecibidos == SOCKET_ERROR)
		{
			return SOCKET_ERROR;
		}

		bytesTotales += bytesRecibidos;
	}

	return SOCKET_EXITO;
}


Mensaje* SocketProtocoloPlano::leerMensaje(){
	char tamanio[PLANO_HEADER_MAX_LONG];
	memset(&tamanio,0,PLANO_HEADER_MAX_LONG);
	tamanio[0]='\0';
	int error = this->receive(tamanio, PLANO_HEADER_MAX_LONG);

	if (error == SOCKET_ERROR)
	{
		return NULL;
	}

	std::string longitud = tamanio;
	unsigned long int tamanioAux=UtilString::stringToInt(longitud);

	char* mensaje = new char[tamanioAux + 1];
	int resultado = this->receive(mensaje, tamanioAux);

	if (resultado == SOCKET_ERROR)
	{
		return NULL;
	}

	mensaje[tamanioAux] = '\0';

	std::string serializedMensaje;
	serializedMensaje = mensaje;

	delete[] mensaje;

	return pp.deserializar(serializedMensaje);
}


SocketProtocoloPlano* SocketProtocoloPlano::accept(){
	int new_fd = Socket::accept();

	if (new_fd > 0){
		SocketProtocoloPlano* nuevoSocket = new SocketProtocoloPlano(new_fd);
		return nuevoSocket;
	} else {
		return NULL;
	}
}
